package cn.gs.util.stream;

// @author gs
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;

public class FileFilter implements FilenameFilter {

    List<Pattern> patterns;

    public FileFilter(List<String> filters) {
        this(filters.toArray(new String[filters.size()]));
    }

    public FileFilter(String... filters) {
        patterns = new ArrayList<Pattern>(filters.length);
        for (String f : filters) {
            Pattern p = Pattern.compile(f.replace("\\", "%").replace("/", "%").replace(".", "@@").replace("**", ".#").replace("*", "[^\\/]*").replace("?", ".").replace("#", "*").replace("@@", "\\.").replace("%", "\\" + File.separator));
            patterns.add(p);
        }
    }

    @Override
    public boolean accept(File dir, String name) {
        String filename = dir.getAbsolutePath() + (dir.getAbsolutePath().endsWith(File.separator) ? "" : File.separator) + name;
        return accept(filename);
    }

    public boolean accept(String filename) {
        for (Pattern p : patterns) {
            if (p.matcher(filename).matches()) {
                return true;
            }
        }
        return false;
    }

    public List<String> listAndFilter(File base) {
        List<String> all = new LinkedList<String>();
        for (File f : base.listFiles()) {
            if (f.isFile()) {
                if (accept(f.getAbsolutePath())) {
                    all.add(f.getAbsolutePath());
                }
            } else if (f.isDirectory()) {
                List<String> subs = listAndFilter(f);
                all.addAll(subs);
            }
        }
        return all;
    }

    public static void main(String[] args) {
        File base = new File(args[0]);
        String[] ns = Arrays.copyOfRange(args, 1, args.length);
        FileFilter filter = new FileFilter(ns);
        List<String> names = filter.listAndFilter(base);
        for (String name : names) {
            System.out.println(name);
        }
    }
}
